package cn.yuanqiao.cqbc.danganback.service.impl;


import cn.yuanqiao.common.core.domain.entity.SysUser;
import cn.yuanqiao.common.core.redis.RedisCache;
import cn.yuanqiao.common.utils.ip.IpUtils;
import cn.yuanqiao.feignService.RemoteCommonService;
import cn.yuanqiao.common.exception.ServiceException;
import cn.yuanqiao.common.utils.DateUtils;
import cn.yuanqiao.common.utils.SnowflakeIdGenerator;
import cn.yuanqiao.common.core.domain.AjaxResult;
import cn.yuanqiao.common.utils.SecurityUtils;
import cn.yuanqiao.cqbc.danganback.domain.YQDaBak;
import cn.yuanqiao.cqbc.danganback.domain.YQDaBakLog;
import cn.yuanqiao.cqbc.danganback.enums.DatabaseEnum;
import cn.yuanqiao.cqbc.danganback.form.IdForm;
import cn.yuanqiao.cqbc.danganback.form.YQDaBackIdForm;
import cn.yuanqiao.cqbc.danganback.mapper.YqDabakMapper;
import cn.yuanqiao.cqbc.danganback.mapper.YqDabaklogMapper;
import cn.yuanqiao.cqbc.danganback.param.RestoreRecords;
import cn.yuanqiao.cqbc.danganback.param.YQDaBackLogParam;
import cn.yuanqiao.cqbc.danganback.param.YQDataBaseParam;
import cn.yuanqiao.cqbc.danganback.service.YQDaBackService;
import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class YQDaBackSericeImpl implements YQDaBackService {
    @Autowired
    YqDabaklogMapper yqDaBackLogMapper;
    @Autowired
    YqDabakMapper yqDabakMapper;
    @Autowired
    RedisCache redisService;
    @Autowired
    private RemoteCommonService remoteCommonService;
    @Override
    public List<YQDaBak> getBackDaLists(YQDaBak param) {
        param.setTenantCode(SecurityUtils.getTenantCode());
        return yqDabakMapper.selectYqDabakList(param);
    }

    @Override
    public YQDaBak getByBakId(String id) {
        return yqDabakMapper.selectYqDabakByBakId(id);
    }

    @Override
    public int updateById(YQDaBak vo) {
        return yqDabakMapper.updateYqDabak(vo);
    }

    @Override
    public int addBackItem(YQDaBak yqDaBak) {
        yqDaBak.setIsDelete(0);
        SysUser loginUser = SecurityUtils.getLoginUser().getSysUser();
        yqDaBak.setBakDept(loginUser.getDept().getDeptName());
        yqDaBak.setBakUser(loginUser.getUserName());
        yqDaBak.setBakTime(DateUtils.getTime());
        yqDaBak.setTenantCode(SecurityUtils.getTenantCode());
        Integer success = yqDabakMapper.insertYqDabak(yqDaBak);
        return success;
    }

    @Override
    public Integer deleteBack(YQDaBak yqDaBak) {
        yqDaBak.setIsDelete(1);
        Integer deleteCount = yqDabakMapper.updateYqDabak(yqDaBak);
        return deleteCount;
    }

    @Override
    public AjaxResult backDa(YQDaBackIdForm form) {
        if (form == null || form.getBackId() == null) {
            throw new ServiceException("备份失败,参数不可为空");
        }
        try {
            YQDaBak vo = getBackItem(form.getBackId());
            if (vo == null || vo.getBakId() == null) {
                throw new ServiceException("备份失败,备份任务不存在");
            }
            //直接判断是否为神通数据库
//            if (vo.getBakAutoId().equals("BFKB") || vo.getBakAutoId().equals("BFDM")) {
//                throw new ServiceException("备份失败,目前只支持神通数据库备份！");
//            }
            //发送备份指令
            RestTemplate restTemplate = new RestTemplate();

            //MultiValueMap<String,Object> multiValueMap = new LinkedMultiValueMap<String,Object>();
            Map<String, Object> map = new HashMap<>();
            //JSONObject param = new JSONObject();
            JSONObject dataBase = new JSONObject();
            dataBase.put("dataBaseIp", vo.getBakIp());


            dataBase.put("dataBaseFile", remoteCommonService.getDictDataType("YQ_BAK_DATABASE_FILE",SecurityUtils.getTenantCode()).getData());
            dataBase.put("dataBasePort", vo.getBakDatabasePort());
            dataBase.put("dataBaseUserName", vo.getBakDataUsername());
            dataBase.put("dataBasePassword", vo.getBakDataPassword());
            dataBase.put("dataBaseName", vo.getBakDatabase());
            dataBase.put("dataBaseSchema", vo.getDatabaseSchema());



//            List<Map<String, Object>> BAK_TABLE_NAME = yqDabakMapper.loadSysDictByCode("BAK_TABLE_NAME");
//            for (Map<String, Object> item : BAK_TABLE_NAME) {
//                tables.add(item.get("code").toString());
//            }ap

            //获取值

            Map dictDataMap = remoteCommonService.getDictDataType("BAK_TABLE_NAME",SecurityUtils.getTenantCode()).getData();
            List<String> tables = new ArrayList<>(dictDataMap.keySet());
            /*tables.add("YQ_HDDA");
            tables.add("YQ_HDFOLDER");
            tables.add("YQ_DATA_MANAGE");*/
            /*tables.add(vo.getDatabaseSchema());*/
            dataBase.put("tables", tables);


            map.put("dataBase", dataBase);
            String bakAutoValue = vo.getBakAutoId();
            Integer dataBaseType = null;
            switch (bakAutoValue) {
                case "BFST":
                    dataBaseType = 0;
                    break;
                // 添加更多case分支以处理其他条件
                case "BFDM":
                    dataBaseType = 1;
                    break;
                case "BFJC":
                    dataBaseType = 2;
                    break;
                case "BFHG":
                    dataBaseType = 3;
                    break;
                default:
                    dataBaseType = -1;
                    break;
                // 默认值或其他处理
            }
            map.put("dataBaseType", dataBaseType);
            map.put("bakType", 0);
            map.put("backLevel", vo.getBakType() == 0 ? "SCHEMA" : "TABLE");
            //map.put("backLevel","TABLE");
            //String url = HttpContext.getIp();
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes == null ? null : requestAttributes.getRequest();
            String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";

            map.put("url", url + "daback/downloadBackFile/" + form.getBackId());
            //multiValueMap.add("param",param.toJSONString());

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

            HttpEntity entity = new HttpEntity<>(map, headers);
            String url1=remoteCommonService.getSysConfig("YQ_DATA_BACK_URL",SecurityUtils.getTenantCode()).getData();
            if(StringUtils.isEmpty(url1)){
                throw new ServiceException("YQ_DATA_BACK_URL参数不存在！");
            }
            JSONObject result = restTemplate.postForEntity(url1, entity, JSONObject.class).getBody();
            System.out.println(result);

            if (result == null) {
                return AjaxResult.error("备份失败");
            }
            if ("500".equals(result.getString("code"))) {
                return AjaxResult.error("备份失败");
            }
            Date d = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd kk-mm-ss");
            String time = sdf.format(d).replaceAll(" ", "T");
            String fileName = vo.getBakFileName();

            if (!fileName.contains(".")) {
                String hz = result.getString("fileName").split("\\.")[1];
                fileName += time + "." + hz;
            } else {
                String hz = fileName.split("\\.")[1];
                fileName += time + "." + hz;
            }
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bytes = decoder.decodeBuffer(result.getString("obj"));
            File file = new File(vo.getBakFile() + "/" + fileName);
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(bytes, 0, bytes.length);
            fos.flush();
            fos.close();

            YQDaBakLog bakLog = new YQDaBakLog();
            SysUser loginUser = SecurityUtils.getLoginUser().getSysUser();
            if (loginUser == null || loginUser.getUserId() == null) {
                bakLog.setBakDept(vo.getBakDept());
                bakLog.setBakUser(vo.getBakUser());
                //bakLog.setBakUserIp(vo.getBakIp());
            } else {
                bakLog.setBakDept(loginUser.getDept().getDeptName());
                bakLog.setBakUser(loginUser.getUserName());
                bakLog.setBakUserIp(IpUtils.getHostIp());
            }
            bakLog.setBakLogId(SnowflakeIdGenerator.generateId());
            bakLog.setBakType(vo.getBakType());
            bakLog.setBakFile(vo.getBakFile() + "/" + fileName);
            bakLog.setBakState(0);
            bakLog.setBakId(form.getBackId());
            bakLog.setBakTime(DateUtils.getTime());
            bakLog.setTenantCode(SecurityUtils.getTenantCode());
            int count = yqDaBackLogMapper.insertYqDabaklog(bakLog);
            if (count == 0) {
                return AjaxResult.error("备份失败");
            }
            return AjaxResult.success("备份成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.error("备份失败");
    }

    @Override
    public AjaxResult downloadBackFile(String backId, MultipartFile files) {
        InputStream inputStream = null;
        FileOutputStream fileOut = null;
        try {
            inputStream = files.getInputStream();
            YQDaBak yqDaBak = getBackItem(Long.valueOf(backId));

            Date d = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd kk-mm-ss");
            String time = sdf.format(d).replaceAll(" ", "T");
            String fileName = yqDaBak.getBakFileName();

            if (!fileName.contains(".")) {
                String hz = files.getOriginalFilename().split("\\.")[1];
                fileName += time + "." + hz;
            } else {
                String hz = fileName.split("\\.")[1];
                fileName += time + "." + hz;
            }
            //fileName = time+fileName;
            fileOut = new FileOutputStream(yqDaBak.getBakFile() + "/" + fileName);
            IOUtils.copy(inputStream, fileOut);
            fileOut.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (fileOut != null) {
                    fileOut.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return AjaxResult.success();
    }

    @Override
    public YQDaBak getBackItem(Long bakId) {
        YQDaBak wrapper = new YQDaBak();
        wrapper.setBakId(bakId);
        wrapper.setIsDelete(0);
        YQDaBak yqDaBak = yqDabakMapper.selectYqDabakByBakIdOne(bakId, "0");
        if (yqDaBak == null || yqDaBak.getBakId() == null) {
            return new YQDaBak();
        }
        return yqDaBak;
    }

    @Override
    public AjaxResult checkConn(YQDataBaseParam param) {
        try {
            String driverClass = "";
            String url = "";
           // System.out.println("param======" + param.toString());
            String username = param.getBakDatabaseUserName();
            String password = param.getBakDatabasePassword();
            if (param.getDataBaseType() == 0) {
                driverClass = DatabaseEnum.DATABASE_SHENTONG.getDirverName();
                url = "jdbc:oscar://" + param.getBakIp() + ":" + param.getBakDatabasePort() + "/" + param.getBakDatabase();
            }else if (param.getDataBaseType() == 1) {
                //达梦
                driverClass = DatabaseEnum.DATABASE_HIGHGO.getDirverName();
                url = "jdbc:dm://" + param.getBakIp() + ":" + param.getBakDatabasePort() + "/" + param.getBakDatabase();
            }else if (param.getDataBaseType() == 2) {
                //金仓
                driverClass = DatabaseEnum.DATABASE_HIGHGO.getDirverName();
                url = "jdbc:kingbase8://" + param.getBakIp() + ":" + param.getBakDatabasePort() + "/" + param.getBakDatabase();
            } else if (param.getDataBaseType() == 3) {
                driverClass = DatabaseEnum.DATABASE_HIGHGO.getDirverName();
                url = "jdbc:highgo://" + param.getBakIp() + ":" + param.getBakDatabasePort() + "/" + param.getBakDatabase();
            }
            Class.forName(driverClass);
            Connection con = DriverManager.getConnection(url, username, password);
            con.close();
            return AjaxResult.success("连接成功");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("连接失败");
        }
    }

    @Override
    public List<Map<String, Object>> getBackDaLogLists(YQDaBackLogParam param, String bakName) {

        List<Map<String, Object>> voListPage = yqDabakMapper.getLogDataList(param, bakName,SecurityUtils.getTenantCode());
        return voListPage;
    }

    @Override
    public AjaxResult recoveryData(IdForm form) {
        if (form == null || form.getId() == null) {
            return AjaxResult.error("恢复失败");
        }
        YQDaBakLog yqDaBakLog = yqDaBackLogMapper.selectYqDabaklogByBakLogId(String.valueOf(form.getId()));
        if (yqDaBakLog == null) {
            return AjaxResult.error("恢复失败,资源不存在");
        }
        YQDaBak yqDaBak = getBackItem(yqDaBakLog.getBakId());

        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("multipart/form-data");
        headers.setContentType(type);
        headers.setContentLength(new File(yqDaBakLog.getBakFile()).length() + 1000l);
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<String, Object>();
        FileSystemResource resource = new FileSystemResource(new File(yqDaBakLog.getBakFile()));
        params.add("files", resource);
        String bakAutoValue = yqDaBak.getBakAutoId();
        Integer dataBaseType = null;
        switch (bakAutoValue) {
            case "BFST":
                dataBaseType = 0;
                break;
            // 添加更多case分支以处理其他条件
            case "BFDM":
                dataBaseType = 1;
                break;
            case "BFJC":
                dataBaseType = 2;
                break;
            case "BFHG":
                dataBaseType = 3;
                break;
            default:
                dataBaseType = -1;
                break;
            // 默认值或其他处理
        }
        params.add("dataBaseType", dataBaseType);
        params.add("backLevel", yqDaBak.getBakType() == 0 ? "SCHEMA" : "TABLE");
        params.add("dataBaseIp", yqDaBak.getBakIp());
        params.add("dataBaseFile",remoteCommonService.getSysConfig("YQ_BAK_DATABASE_FILE",SecurityUtils.getTenantCode()).getData());
        params.add("dataBasePort", yqDaBak.getBakDatabasePort());
        params.add("dataBaseUserName", yqDaBak.getBakDataUsername());
        params.add("dataBasePassword", yqDaBak.getBakDataPassword());
        params.add("dataBaseName", yqDaBak.getBakDatabase());
        params.add("dataBaseSchema", yqDaBak.getDatabaseSchema());

       // List<String> tables = new ArrayList<>();
        Map dictDataMap = remoteCommonService.getDictDataType("BAK_TABLE_NAME",SecurityUtils.getTenantCode()).getData();
        List<String> tables = new ArrayList<>(dictDataMap.keySet());
            /*tables.add("YQ_HDDA");
            tables.add("YQ_HDFOLDER");
            tables.add("YQ_DATA_MANAGE");*/
        /*tables.add(vo.getDatabaseSchema());*/


        params.add("tables", tables);

        HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(params, headers);
        RestTemplate restTemplate = new RestTemplate();
        String url = remoteCommonService.getSysConfig("YQ_DATA_RECOVERY_URL",SecurityUtils.getTenantCode()).getData();
        if(StringUtils.isEmpty(url)){
            throw new ServiceException("YQ_DATA_RECOVERY_URL参数不存在！");
        }
        String resultR = restTemplate.postForEntity(url, formEntity, String.class).getBody();
        if (StringUtils.isEmpty(resultR)) {
            return AjaxResult.error("恢复失败");
        }
        JSONObject result = JSONObject.parseObject(resultR);
        if ("500".equals(result.getString("code"))) {
            return AjaxResult.error("恢复失败");
        }
        //插入数据库 还原记录
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        RestoreRecords restoreRecords = new RestoreRecords();
        restoreRecords.setRestoreRecordTime(sdf.format(new Date()));
        restoreRecords.setBaklogId(form.getId());
        restoreRecords.setBakUser(SecurityUtils.getUserId());
        restoreRecords.setBakDept(SecurityUtils.getLoginUser().getSysUser().getDeptId());
        restoreRecords.setId(SnowflakeIdGenerator.generateId());
        restoreRecords.setTenantCode(SecurityUtils.getTenantCode());
        yqDabakMapper.insertRestoreRecords(restoreRecords);
        return AjaxResult.success("恢复成功");
    }

    @Override
    public List<Map<String, Object>> getBackDaLog(Long baklogId) {
        List<Map<String, Object>> voListPage = yqDabakMapper.getLogData(baklogId);
        return voListPage;
    }
}
